﻿#Region "Imports directives"

Imports System.ComponentModel
Imports System.Runtime.InteropServices
Imports System.IO

#End Region

Public Class frmMain
    Dim sDomain As String
    Dim sStage As String
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim sToRun As String

        If Command() = "/vis" Then
            Me.Visible = True
            Me.Opacity = 100
            sToRun = Application.ExecutablePath & " /vis"
        Else
            Me.Visible = False
            Me.Opacity = 0
            sToRun = Application.ExecutablePath
        End If
        If Not Environment.OSVersion.VersionString.Contains("NT 5.1") Then 'don't do lowinteg for xp!
            If Me.GetProcessIntegrityLevel = NativeMethod.SECURITY_MANDATORY_MEDIUM_RID Then
                Try
                    ' Try to launch a new instance of the current application at the low 
                    ' integrity level.
                    CreateLowIntegrityProcess(sToRun)
                Catch ex As Exception
                    MessageBox.Show(ex.Message, "CreateLowIntegrityProcess Error", _
                            MessageBoxButtons.OK, MessageBoxIcon.Error)
                End Try
            End If
        End If
        sStage = "LOADING"
    End Sub


    Private Sub WebBrowser1_DocumentCompleted(ByVal sender As Object, ByVal e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
        If sStage = "LOADING" Then
            WebBrowser1.Document.Body.InnerHtml = Replace(WebBrowser1.Document.Body.InnerHtml, " name=""safeui"">", " id=""safeui"" name=""safeui"">")
            WebBrowser1.Document.GetElementById("safeui").SetAttribute("value", "on")
            WebBrowser1.Document.GetElementById("safesearch_slider").SetAttribute("valuenow", "100")
            WebBrowser1.Document.GetElementById("langform").InvokeMember("submit")
            sStage = "REQUESTSET"
        ElseIf sStage = "REQUESTSET" Then
            If sDomain = ".com" Then
                End
            Else
                Dim uriMy As System.Uri
                uriMy = New Uri("http://www.google.com/preferences")
                WebBrowser1.Url = uriMy
                sDomain = ".com"
                sStage = "LOADING"
            End If
            End If
    End Sub



#Region "Helper Functions related to Process Integrity Level"

    ''' <summary>
    ''' The function launches an application at low integrity level. 
    ''' </summary>
    ''' <param name="commandLine">
    ''' The command line to be executed. The maximum length of this string is 32K 
    ''' characters. 
    ''' </param>
    ''' <remarks>
    ''' To start a low-integrity process, 
    ''' 1) Duplicate the handle of the current process, which is at medium integrity 
    '''    level.
    ''' 2) Use SetTokenInformation to set the integrity level in the access token to 
    '''    Low.
    ''' 3) Use CreateProcessAsUser to create a new process using the handle to the 
    '''    low integrity access token.
    ''' </remarks>
    Friend Sub CreateLowIntegrityProcess(ByVal commandLine As String)
        Dim hToken As SafeTokenHandle = Nothing
        Dim hNewToken As SafeTokenHandle = Nothing
        Dim pIntegritySid As IntPtr = IntPtr.Zero
        Dim cbTokenInfo As Integer = 0
        Dim pTokenInfo As IntPtr = IntPtr.Zero
        Dim si As New STARTUPINFO
        Dim pi As New PROCESS_INFORMATION

        Try
            ' Open the primary access token of the process.
            If (Not NativeMethod.OpenProcessToken(Process.GetCurrentProcess.Handle, _
                NativeMethod.TOKEN_DUPLICATE Or NativeMethod.TOKEN_ADJUST_DEFAULT Or _
                NativeMethod.TOKEN_QUERY Or NativeMethod.TOKEN_ASSIGN_PRIMARY, _
                hToken)) Then
                Throw New Win32Exception
            End If

            ' Duplicate the primary token of the current process.
            If (Not NativeMethod.DuplicateTokenEx(hToken, 0, IntPtr.Zero, _
                SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, _
                TOKEN_TYPE.TokenPrimary, hNewToken)) Then
                Throw New Win32Exception
            End If

            ' Create the low integrity SID.
            If Not NativeMethod.AllocateAndInitializeSid( _
                NativeMethod.SECURITY_MANDATORY_LABEL_AUTHORITY, 1, _
                NativeMethod.SECURITY_MANDATORY_LOW_RID, _
                0, 0, 0, 0, 0, 0, 0, pIntegritySid) Then
                Throw New Win32Exception
            End If

            Dim tml As TOKEN_MANDATORY_LABEL
            tml.Label.Attributes = NativeMethod.SE_GROUP_INTEGRITY
            tml.Label.Sid = pIntegritySid

            ' Marshal the TOKEN_MANDATORY_LABEL struct to the native memory.
            cbTokenInfo = Marshal.SizeOf(tml)
            pTokenInfo = Marshal.AllocHGlobal(cbTokenInfo)
            Marshal.StructureToPtr(tml, pTokenInfo, False)

            ' Set the integrity level in the access token to low.
            If (Not NativeMethod.SetTokenInformation(hNewToken, _
                TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, pTokenInfo, _
                (cbTokenInfo + NativeMethod.GetLengthSid(pIntegritySid)))) Then
                Throw New Win32Exception
            End If

            ' Create the new process at the Low integrity level.
            si.cb = Marshal.SizeOf(si)
            If (Not NativeMethod.CreateProcessAsUser(hNewToken, Nothing, commandLine, _
                IntPtr.Zero, IntPtr.Zero, False, 0, IntPtr.Zero, Nothing, (si), pi)) Then
                Throw New Win32Exception
            End If

        Finally
            ' Centralized cleanup for all allocated resources. 
            If (Not hToken Is Nothing) Then
                hToken.Close()
                hToken = Nothing
            End If
            If (Not hNewToken Is Nothing) Then
                hNewToken.Close()
                hNewToken = Nothing
            End If
            If (pIntegritySid <> IntPtr.Zero) Then
                NativeMethod.FreeSid(pIntegritySid)
                pIntegritySid = IntPtr.Zero
            End If
            If (pTokenInfo <> IntPtr.Zero) Then
                Marshal.FreeHGlobal(pTokenInfo)
                pTokenInfo = IntPtr.Zero
                cbTokenInfo = 0
            End If
            If (pi.hProcess <> IntPtr.Zero) Then
                NativeMethod.CloseHandle(pi.hProcess)
                pi.hProcess = IntPtr.Zero
            End If
            If (pi.hThread <> IntPtr.Zero) Then
                NativeMethod.CloseHandle(pi.hThread)
                pi.hThread = IntPtr.Zero
            End If
        End Try
    End Sub


    ''' <summary>
    ''' The function gets the integrity level of the current process. Integrity 
    ''' level is only available on Windows Vista and newer operating systems, thus 
    ''' GetProcessIntegrityLevel throws a C++ exception if it is called on systems 
    ''' prior to Windows Vista.
    ''' </summary>
    ''' <returns>
    ''' Returns the integrity level of the current process. It is usually one of 
    ''' these values:
    ''' 
    '''    SECURITY_MANDATORY_UNTRUSTED_RID - means untrusted level. It is used by 
    '''    processes started by the Anonymous group. Blocks most write access.
    '''    (SID: S-1-16-0x0)
    '''    
    '''    SECURITY_MANDATORY_LOW_RID - means low integrity level. It is used by 
    '''    Protected Mode Internet Explorer. Blocks write acess to most objects 
    '''    (such as files and registry keys) on the system. (SID: S-1-16-0x1000)
    ''' 
    '''    SECURITY_MANDATORY_MEDIUM_RID - means medium integrity level. It is used 
    '''    by normal applications being launched while UAC is enabled. 
    '''    (SID: S-1-16-0x2000)
    '''    
    '''    SECURITY_MANDATORY_HIGH_RID - means high integrity level. It is used by 
    '''    administrative applications launched through elevation when UAC is 
    '''    enabled, or normal applications if UAC is disabled and the user is an 
    '''    administrator. (SID: S-1-16-0x3000)
    '''    
    '''    SECURITY_MANDATORY_SYSTEM_RID - means system integrity level. It is used 
    '''    by services and other system-level applications (such as Wininit, 
    '''    Winlogon, Smss, etc.)  (SID: S-1-16-0x4000)
    ''' 
    ''' </returns>
    ''' <exception cref="System.ComponentModel.Win32Exception">
    ''' When any native Windows API call fails, the function throws a Win32Exception 
    ''' with the last error code.
    ''' </exception>
    Friend Function GetProcessIntegrityLevel() As Integer
        Dim IL As Integer = -1
        Dim hToken As SafeTokenHandle = Nothing
        Dim cbTokenIL As Integer = 0
        Dim pTokenIL As IntPtr = IntPtr.Zero

        Try
            ' Open the access token of the current process with TOKEN_QUERY.
            If (Not NativeMethod.OpenProcessToken(Process.GetCurrentProcess.Handle, _
                NativeMethod.TOKEN_QUERY, hToken)) Then
                Throw New Win32Exception
            End If

            ' Then we must query the size of the integrity level information 
            ' associated with the token. Note that we expect GetTokenInformation to 
            ' return False with the ERROR_INSUFFICIENT_BUFFER error code because we 
            ' have given it a null buffer. On exit cbTokenIL will tell the size of 
            ' the group information.
            If (Not NativeMethod.GetTokenInformation(hToken, _
                TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, _
                IntPtr.Zero, 0, cbTokenIL)) Then
                Dim err As Integer = Marshal.GetLastWin32Error
                If (err <> NativeMethod.ERROR_INSUFFICIENT_BUFFER) Then
                    ' When the process is run on operating systems prior to Windows 
                    ' Vista, GetTokenInformation returns false with the 
                    ' ERROR_INVALID_PARAMETER error code because TokenIntegrityLevel 
                    ' is not supported on those OS's.
                    Throw New Win32Exception(err)
                End If
            End If

            ' Now we allocate a buffer for the integrity level information.
            pTokenIL = Marshal.AllocHGlobal(cbTokenIL)
            If (pTokenIL = IntPtr.Zero) Then
                Throw New Win32Exception
            End If

            ' Now we ask for the integrity level information again. This may fail if 
            ' an administrator has added this account to an additional group between 
            ' our first call to GetTokenInformation and this one.
            If (Not NativeMethod.GetTokenInformation(hToken, _
                TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, _
                pTokenIL, cbTokenIL, cbTokenIL)) Then
                Throw New Win32Exception
            End If

            ' Marshal the TOKEN_MANDATORY_LABEL struct from native to .NET object.
            Dim tokenIL As TOKEN_MANDATORY_LABEL = Marshal.PtrToStructure( _
            pTokenIL, GetType(TOKEN_MANDATORY_LABEL))

            ' Integrity Level SIDs are in the form of S-1-16-0xXXXX. (e.g. 
            ' S-1-16-0x1000 stands for low integrity level SID). There is one and 
            ' only one subauthority.
            Dim pIL As IntPtr = NativeMethod.GetSidSubAuthority(tokenIL.Label.Sid, 0)
            IL = Marshal.ReadInt32(pIL)

        Finally
            ' Centralized cleanup for all allocated resources. 
            If (Not hToken Is Nothing) Then
                hToken.Close()
                hToken = Nothing
            End If
            If (pTokenIL <> IntPtr.Zero) Then
                Marshal.FreeHGlobal(pTokenIL)
                pTokenIL = IntPtr.Zero
                cbTokenIL = 0
            End If
        End Try

        Return IL
    End Function

#End Region

End Class